package com.ai.networking.netty.client;
 
import com.ai.common.constant.PlcConstants;
import com.ai.entity.network.IdentifySysToL1Message;
import com.ai.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import springfox.documentation.spring.web.json.Json;

import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
/**
 *  蚂蚁舞
 */
@Slf4j
public class BootNettyClientChannelCache {
 
    public static volatile Map<String, BootNettyClientChannel> channelMapCache = new ConcurrentHashMap<String, BootNettyClientChannel>();
 
    public static void add(String code, BootNettyClientChannel channel){
    	channelMapCache.put(code,channel);
    }
 
    public static BootNettyClientChannel get(String code){
        return channelMapCache.get(code);
    }
 
    public static void remove(String code){
    	channelMapCache.remove(code);
    }

    public static void clientSendMessage(String code, IdentifySysToL1Message identifySysToL1Message) {
        log.info("=========================== ## BootNettyClientChannelCache.clientSendMessage ##  ===========================");
        log.info("===========================  发送给PLC消息  ===========================");
        log.info("===========================  链路code：{} ===========================",code);
        log.info("===========================  发送消息内容:{} ===========================",JSONObject.toJSONString(identifySysToL1Message));
//        IdentifySysToL1Message identifySysToL1Message = JSONObject.parseObject(msg, IdentifySysToL1Message.class);
        byte[] message=new byte[46];
        if (code.equals(PlcConstants.PLC_1_CODE)){
            message = createMessageToPlc1(identifySysToL1Message);
        }else {
            message = createMessageToPlcOther(identifySysToL1Message);
        }
        log.info("===========================  报文组建完毕：{}  ===========================",new String(message));
        for (String key : channelMapCache.keySet()) {
            log.info("+++++++++++  key:{}  +++++++++++++++",key);
        }
        Channel channel = channelMapCache.get(code).getChannel();
        log.info("===========================  获取channel 开始发送报文  ===========================");
        channel.writeAndFlush(Unpooled.copiedBuffer(message));
        channel.flush();
    }

    /**
     * 創建給其他plc的回調信息
     * @param identifySysToL1Message
     * @return
     */
    public static byte[] createMessageToPlcOther(IdentifySysToL1Message identifySysToL1Message) {
        log.info("=========================== ## BootNettyClientChannelCache.createMessageToPlcOther  begin ##  ===========================");
        log.info("===========================  发送消息原内容：{}  ===========================",JSONObject.toJSONString(identifySysToL1Message));
        log.info("===========================  开始组建消息  ===========================");
        Integer messageLength=46;
        String telId = String.valueOf(identifySysToL1Message.getTelID());
        String planNo = identifySysToL1Message.getPlanNo();
        String doorNum = identifySysToL1Message.getDoorNum();
        Integer result = identifySysToL1Message.getResult();
        byte[] messageBytes = new byte[messageLength];
        // 消息長度 2
//        StringUtil.byteInsert(messageBytes, StringUtil.intToByteArray(messageLength,1),0);
        StringUtil.byteInsert(messageBytes, StringUtil.intToByteArray(messageLength,1),1);
        // 信號telId 6位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(telId),2);
        // 板坯號 12位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(planNo),8);
        //爐門編號 2位
//        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(Integer.parseInt(doorNum),1),20);
        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(Integer.parseInt(doorNum),1),21);
        //識別結果 2位
//        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(result,1),22);
        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(result,1),23);
        //預留字段 22位
        String spare= (StringUtils.isBlank(identifySysToL1Message.getSpare())?"":identifySysToL1Message.getSpare());
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(spare),24);

        String messageToPlc = Arrays.toString(messageBytes);
        log.info("=========================== 消息组件完毕：  ===========================");
        log.info("=========================== ## BootNettyClientChannelCache.createMessageToPlcOther  end ##  ===========================");

        return messageBytes;
    }



    /**
     * 創建給其他plc1的回調信息
     * @param identifySysToL1Message
     * @return
     */
    public static byte[] createMessageToPlc1(IdentifySysToL1Message identifySysToL1Message){
        short messageLength=46;
        byte[] messageBytes = new byte[46];
        // 消息長度 2
//        StringUtil.byteInsert(messageBytes, StringUtil.intToByteArray(messageLength,1),0);
        StringUtil.byteInsert(messageBytes, StringUtil.intToByteArray(messageLength,1),1);
        // 信號telId 6位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(identifySysToL1Message.getTelID().toString()),2);
        // 板坯號 12位
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(identifySysToL1Message.getPlanNo()),8);
        //識別結果 2位
//        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(identifySysToL1Message.getResult(),2),20);
        StringUtil.byteInsert(messageBytes,StringUtil.intToByteArray(identifySysToL1Message.getResult(),2),21);
        //預留字段 24位
        String spare= (StringUtils.isBlank(identifySysToL1Message.getSpare())?"":identifySysToL1Message.getSpare());
        StringUtil.byteInsert(messageBytes,StringUtil.convertStringToHex(spare),22);

        String messageToPlc1 = Arrays.toString(messageBytes);
        return messageBytes;
    }

    /**
     * 当前建立过连接的所有信道，
     * 将这些数据追加到内存中，并通过key--value的形式进行存储
     * @param code
     * @param channel
     */
    public static void save(String code, BootNettyClientChannel channel) {
        if(channelMapCache.get(code) == null) {
            add(code,channel);
        }
    }
}